﻿using System;
using System.Configuration;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Data;
using System.Data.SqlClient;
using System.ComponentModel;
using System.Threading.Tasks;
using GanagroLiteData;
using Csla.Validation;
using GeneralUtilities;

namespace GanagroLiteBO
{
    public partial class GANADO_BO 
    {
        private bool _isnew = false;
        private bool _validationrulesSuspended = false;
        private List<string> Contenedor = new List<string>();

        #region Constructors
        public GANADO_BO()
        {
            _isnew = true;
            AddBusinessRules();

        }

        public GANADO_BO(string codigo)
        {
            using (GlContext gContext = new GlContext())
            {
                GANADO currentGanadoDO = gContext.GANADOes.FirstOrDefault(q => q.CODIGO == codigo);
                if (currentGanadoDO != null)
                {
                    utilities.CopyProperties(currentGanadoDO, this, null);
                }
                _isnew = false;

                AddBusinessRules();
            }
        }

        public GANADO_BO(List<string> ListaDeCodigos)
        {
            _isnew = true;
            Contenedor = ListaDeCodigos;
            AddBusinessRulesWithContenedor(); 
        }

       #endregion

        #region public properties
        public string  TipoSalidaDesc { get; set; }
        public string Tatuaje { get; set; }
        #endregion

        #region Public Methods

        public void Load(string codigo)
        {
            using (GlContext glContext = new GlContext())
            {
                GANADO currentGanadoDO = glContext.GANADOes.FirstOrDefault(q => q.CODIGO == codigo);
                if (currentGanadoDO != null)
                {
                    this.SuspendValidation();
                    utilities.CopyProperties(currentGanadoDO, this, null);
                    _isnew = false;
                }
            }
        }

        public void Guardar()
        {
            GANADO currentGanadoDO = new GANADO();
            utilities.CopyProperties(this, currentGanadoDO, null);

            using (GlContext gContext = new GlContext())
            {
                if (_isnew)
                {
                    gContext.GANADOes.Add(currentGanadoDO);
                }
                else
                {
                    gContext.GANADOes.Attach(currentGanadoDO);
                    gContext.Entry(currentGanadoDO).State = System.Data.Entity.EntityState.Modified;
                }
                gContext.SaveChanges();
            }
        }

        public bool Guardar(ref bool success)
        {
            try
            {
                GANADO currentGanadoDO = new GANADO();
                utilities.CopyProperties(this, currentGanadoDO, null);
                using (GlContext gContext = new GlContext())
                {
                    if (_isnew)
                    {
                        gContext.GANADOes.Add(currentGanadoDO);
                    }
                    else
                    {
                        gContext.GANADOes.Attach(currentGanadoDO); //TODO: test this
                        gContext.Entry(currentGanadoDO).State = System.Data.Entity.EntityState.Modified;
                    }
                    gContext.SaveChanges();
                }
                success = true;
            }
            catch
            {
                success = false;
            }

            return success;
        }

        public void SuspendValidation()
        {
            _validationrulesSuspended = true;
        }

        public void DarDeBaja(DateTime fechaSalida,TiposOperacion tOp)
        {
            GANADO currentGanadoDO = new GANADO();
            utilities.CopyProperties(this, currentGanadoDO, null);

            using (GlContext gContext = new GlContext())
            {
                gContext.GANADOes.Attach(currentGanadoDO);
                currentGanadoDO.Activo = 0;
                currentGanadoDO.FECHASAL = fechaSalida;
                currentGanadoDO.TIPOSALIDA = (byte)tOp;
                gContext.SaveChanges();
            }
        }

        public void DarDeAlta()
        {
            GANADO currentGanadoDO = new GANADO();
            utilities.CopyProperties(this, currentGanadoDO, null);
            using (GlContext gContext = new GlContext())
            {
                gContext.GANADOes.Attach(currentGanadoDO);
                currentGanadoDO.Activo = 1;
                currentGanadoDO.FECHASAL = null;
                currentGanadoDO.TIPOSALIDA = null;
                gContext.SaveChanges();
            }
        }

        public void Delete()
        {
            GANADO currentGanadoDO = new GANADO();
            utilities.CopyProperties(this, currentGanadoDO, null);

            using (GlContext gContext = new GlContext())
            {
                gContext.GANADOes.Remove(currentGanadoDO);
                gContext.SaveChanges();
            }
        }

        public static string ListaPesajes(string codigo)
        {
            string listaPesajes = string.Empty;
            using (GlContext gContext = new GlContext())
            {

                var pesajes = from items in gContext.PESAJES
                              where items.Codigo == codigo
                              orderby items.Fecha
                              select new { items.Fecha, items.Peso  };

                foreach (var item in pesajes)
                {
                    listaPesajes = listaPesajes + string.Format("{0} : {1}\r\n", item.Fecha.ToShortDateString(), item.Peso.ToString());
                }
            }
                return listaPesajes;
        }

        public DataTable PesajesBO
        {
            get
            {
                DataTable DT = UtilityDB.PopulateDTFromSQL(string.Format("SELECT FECHA,Peso,Promedio as Ganancia FROM RepPesajesYGanancia WHERE CODIGO ='{0}' ORDER BY FECHA", this.CODIGO));
                return DT;
            }
        }

        public Operaciones ListOperaciones
        {
            get
            {
                Operaciones lOp = new Operaciones();
                using (GlContext gContext = new GlContext())
                {
                    GANADO currentGanadoDO = gContext.GANADOes.FirstOrDefault(q => q.CODIGO == this.CODIGO);
                    if (currentGanadoDO != null)
                    {
                        var q2 = from items in currentGanadoDO.PESAJES
                                 orderby items.Fecha descending
                                 select new
                                 {
                                     Codigo = items.Codigo,
                                     Fecha = items.Fecha,
                                     Peso = (short)items.Peso,
                                     Operacion = items.Operacion,
                                     ID = items.ID
                                 };

                        DateTime fechaUltOp = currentGanadoDO.OPERACIONES.Max(p => p.FECHA);
                        if (q2.First().Fecha < fechaUltOp)
                        {
                            var q3 = from item in currentGanadoDO.OPERACIONES
                                     where item.CODIGO == currentGanadoDO.CODIGO && item.FECHA == fechaUltOp
                                     orderby item.FECHA descending
                                     select new
                                     {
                                         Codigo = item.CODIGO,
                                         Fecha = item.FECHA,
                                         Peso = (short)(item.VALOR1 ?? 0),
                                         Operacion = item.OPERACION,
                                         ID = item.ID
                                     };

                            lOp.Add(new Operacion_BO(q3.First().Codigo, q3.First().Fecha, (TiposOperacion)q3.First().Operacion, (short?)q3.First().Peso, q3.First().ID));
                        }

                        foreach (var item in q2)
                        {
                            lOp.Add(new Operacion_BO(item.Codigo, item.Fecha, (TiposOperacion)item.Operacion, (short?)item.Peso, item.ID));
                        }

                        return lOp;
                    }
                    else
                    {
                        return null;
                    }
                }
            }
        }

        public async Task<int> GetGananciaVida()
        {
            int ganancia = 0;
            await Task.Run(() => int.TryParse(GeneralUtilities.UtilityDB.GetGananciaVida(_CODIGO),out ganancia));
            return ganancia;
        }
        public static bool Exists(string codigo)
        {
            if (string.IsNullOrEmpty(codigo))
            {
                return false;
            }

            using (GlContext gContext = new GlContext())
            {
                return (gContext.GANADOes.Any(q => q.CODIGO == codigo));
            }
        }

        public static bool Exists(string codigo, bool activo)
        {
            if (string.IsNullOrEmpty(codigo))
            {
                return false;
            }

            using (GlContext gContext = new GlContext())
            {
                return (gContext.GANADOes.Any(q => q.CODIGO == codigo && q.Activo == Convert.ToByte(activo)));
            }
        }

        #endregion

        #region Validations
        private ValidationRules _validationRules;
        public ValidationRules ValidationRules
        {
            get
            {
                if (_validationRules == null)
                    _validationRules = new ValidationRules(this);
                return _validationRules;
            }
        }

        public bool Isvalid()
        {
            return Isvalid(_validationrulesSuspended);
        }

        public bool Isvalid(bool BypassValidation)
        {
            if (BypassValidation == false)
            {
                ValidationRules.CheckRules();
            }

            return ValidationRules.GetBrokenRules().ErrorCount == 0;
        }

        public bool CodigoEsValido(ref string errormessage)
        {
            errormessage = string.Empty;
            bool success = true;

            if (Exists(_CODIGO) == false)
            {
                errormessage = "El codigo No Existe en la base de datos";
                success = false;
            }

            return success;
        }

        private static bool CodigoEsValido<T>(T target, Csla.Validation.RuleArgs e) where T : GANADO_BO
        {
            bool success = Exists(target._CODIGO);

            if (success == false)
            {
                e.Description = "El codigo No Existe en la base de datos";
            }

            return success;
        }

        protected static bool CodigoEnContenedor<T>(T target, Csla.Validation.RuleArgs e) where T : GANADO_BO
        {
            bool isvalid = true;

            if (target.Contenedor == null)
            {
                return true;
            }

            isvalid = utilities.NoDuplicates(target.CODIGO, target.Contenedor);
            if (isvalid == false)
            {
                e.Description = "Codigo ya esta definido en este grupo";
            }
            return isvalid;
        }


        private void AddBusinessRulesWithContenedor()
        {
            AddBusinessRules();
            ValidationRules.AddRule(new Csla.Validation.RuleHandler<GANADO_BO, RuleArgs>(CodigoEnContenedor), "CODIGO");
        }

        private void AddBusinessRules()
        {
            try
            {
                ValidationRules.AddRule(new Csla.Validation.RuleHandler<GANADO_BO, RuleArgs>(CodigoEsValido), "CODIGO");
            }
            catch (Exception ex)
            {
                throw (new Exception("AddBusinessRules: " + ex.Message, ex));
            }

        }

        #endregion

        #region INotifyPropertyChanged Implementation
        protected void FirePropertyChangedNotification(string propName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propName));
            }
            ValidationRules.CheckRules(propName);
        }

        public event PropertyChangedEventHandler PropertyChanged;
        #endregion

        #region IDataErrorInfo Members

        //				    private string m_Error = string.Empty;
        //				    private Hashtable m_PropErrors = new Hashtable();

        [Browsable(false)]
        public string Error
        {
            get
            {
                if (!ValidationRules.IsValid)
                { return ValidationRules.GetBrokenRules().ToString(Csla.Validation.RuleSeverity.Error); }
                else
                { return String.Empty; }
            }
        }

        [Browsable(false)]
        public string this[string columnName]
        {
            get
            {
                string result = string.Empty;
                if (!ValidationRules.IsValid)
                {
                    BrokenRule rule = ValidationRules.GetBrokenRules().GetFirstBrokenRule(columnName);
                    if (rule != null)
                        result = rule.Description;
                }
                return result;
            }
        }
        #endregion

        #region IEditableObject Members

        public void BeginEdit()
        {
            if (!m_Editing)
            {
            }

            m_Editing = true;
        }

        public void CancelEdit()
        {
            m_Editing = false;
        }

        public void EndEdit()
        {
            if (m_Editing)
            {
            }

            m_Editing = false;
        }

        #endregion

    }
}
